"""
预警和疏散系统服务
实现异常聚集的实时检测和告警、疏散路径的智能规划、预警信息的推送和处理
"""
import asyncio
import logging
import numpy as np
from datetime import datetime, timedelta
from typing import List, Dict, Optional, Tuple, Any, Set
from uuid import uuid4
from collections import defaultdict, deque
from dataclasses import dataclass, field
from enum import Enum
import json
import heapq

from schemas.ai_algorithm import AlertLevel, BehaviorType
from schemas.person_detection import PersonDetectionResult
from services.campus_crowd_safety.crowd_density_analysis_service import (
    DensityMeasurement, DensityLevel, Zone, DensityAnomaly
)
from core.config import get_settings

logger = logging.getLogger(__name__)
settings = get_settings()


class EmergencyLevel(str, Enum):
    """紧急程度枚举"""
    NORMAL = "normal"
    CAUTION = "caution"
    WARNING = "warning"
    EMERGENCY = "emergency"
    CRITICAL = "critical"


class EvacuationStatus(str, Enum):
    """疏散状态枚举"""
    STANDBY = "standby"
    INITIATED = "initiated"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    CANCELLED = "cancelled"


class RouteStatus(str, Enum):
    """路径状态枚举"""
    AVAILABLE = "available"
    CONGESTED = "congested"
    BLOCKED = "blocked"
    EMERGENCY_ONLY = "emergency_only"


@dataclass
class ExitPoint:
    """出口点"""
    exit_id: str
    exit_name: str
    coordinates: Tuple[float, float]
    capacity: int  # 每分钟通过人数
    current_load: int = 0
    status: RouteStatus = RouteStatus.AVAILABLE
    is_emergency_exit: bool = False
    accessibility_features: List[str] = field(default_factory=list)  # 无障碍特性
    
    def get_efficiency(self) -> float:
        """获取出口效率（0-1）"""
        if self.status == RouteStatus.BLOCKED:
            return 0.0
        elif self.status == RouteStatus.CONGESTED:
            return 0.3
        elif self.status == RouteStatus.EMERGENCY_ONLY:
            return 0.5 if self.is_emergency_exit else 0.1
        else:
            load_ratio = self.current_load / self.capacity if self.capacity > 0 else 0
            return max(0.1, 1.0 - load_ratio)


@dataclass
class EvacuationRoute:
    """疏散路径"""
    route_id: str
    route_name: str
    start_zone: str
    end_exit: str
    waypoints: List[Tuple[float, float]]
    distance: float
    estimated_time: float  # 预估疏散时间（分钟）
    capacity: int  # 路径容量
    current_occupancy: int = 0
    status: RouteStatus = RouteStatus.AVAILABLE
    priority: int = 1  # 优先级（1-5，5最高）
    accessibility_level: int = 1  # 无障碍级别（1-3，3最高）
    
    def get_congestion_level(self) -> float:
        """获取拥堵程度（0-1）"""
        return self.current_occupancy / self.capacity if self.capacity > 0 else 0
    
    def get_route_score(self, emergency_level: EmergencyLevel) -> float:
        """获取路径评分"""
        if self.status == RouteStatus.BLOCKED:
            return 0.0
        
        # 基础分数
        base_score = 1.0
        
        # 距离因子（距离越短越好）
        distance_factor = max(0.1, 1.0 - self.distance / 1000.0)
        
        # 拥堵因子
        congestion_factor = max(0.1, 1.0 - self.get_congestion_level())
        
        # 优先级因子
        priority_factor = self.priority / 5.0
        
        # 紧急情况下的调整
        if emergency_level in [EmergencyLevel.EMERGENCY, EmergencyLevel.CRITICAL]:
            # 紧急情况下优先考虑容量和优先级
            base_score *= (priority_factor * 0.4 + congestion_factor * 0.6)
        else:
            # 正常情况下平衡各因素
            base_score *= (distance_factor * 0.3 + congestion_factor * 0.4 + priority_factor * 0.3)
        
        return base_score


@dataclass
class EvacuationPlan:
    """疏散计划"""
    plan_id: str
    plan_name: str
    trigger_conditions: Dict[str, Any]
    affected_zones: List[str]
    evacuation_routes: List[str]  # 路径ID列表
    estimated_duration: float  # 预估疏散时间（分钟）
    max_occupancy: int  # 最大疏散人数
    priority_groups: List[str] = field(default_factory=list)  # 优先疏散群体
    emergency_level: EmergencyLevel = EmergencyLevel.WARNING
    created_at: datetime = field(default_factory=datetime.now)
    
    def is_triggered(self, current_conditions: Dict[str, Any]) -> bool:
        """判断是否触发疏散计划"""
        for condition_key, condition_value in self.trigger_conditions.items():
            current_value = current_conditions.get(condition_key)
            
            if isinstance(condition_value, dict):
                operator = condition_value.get('operator', '>=')
                threshold = condition_value.get('value')
                
                if operator == '>=' and current_value < threshold:
                    return False
                elif operator == '>' and current_value <= threshold:
                    return False
                elif operator == '<=' and current_value > threshold:
                    return False
                elif operator == '<' and current_value >= threshold:
                    return False
                elif operator == '==' and current_value != threshold:
                    return False
            else:
                if current_value != condition_value:
                    return False
        
        return True


@dataclass
class EvacuationEvent:
    """疏散事件"""
    event_id: str
    plan_id: str
    camera_id: str
    trigger_time: datetime
    status: EvacuationStatus
    emergency_level: EmergencyLevel
    affected_zones: List[str]
    estimated_people: int
    evacuation_routes: List[str]
    progress: float = 0.0  # 疏散进度（0-1）
    completion_time: Optional[datetime] = None
    cancelled_time: Optional[datetime] = None
    cancellation_reason: Optional[str] = None
    metadata: Dict[str, Any] = field(default_factory=dict)


class PathfindingAlgorithm:
    """路径规划算法"""
    
    def __init__(self):
        self.grid_size = 10  # 网格大小
        self.obstacle_penalty = 1000  # 障碍物惩罚
    
    def find_optimal_routes(
        self,
        start_zones: List[Zone],
        exit_points: List[ExitPoint],
        obstacles: List[Tuple[float, float, float, float]] = None,
        emergency_level: EmergencyLevel = EmergencyLevel.WARNING
    ) -> List[EvacuationRoute]:
        """查找最优疏散路径"""
        routes = []
        
        for zone in start_zones:
            zone_center = self._get_zone_center(zone)
            
            # 为每个出口计算路径
            for exit_point in exit_points:
                if emergency_level == EmergencyLevel.CRITICAL or exit_point.status != RouteStatus.BLOCKED:
                    route = self._calculate_route(
                        zone, zone_center, exit_point, obstacles, emergency_level
                    )
                    if route:
                        routes.append(route)
        
        # 按评分排序
        routes.sort(key=lambda r: r.get_route_score(emergency_level), reverse=True)
        
        return routes
    
    def _get_zone_center(self, zone: Zone) -> Tuple[float, float]:
        """获取区域中心点"""
        if not zone.coordinates:
            return (0, 0)
        
        x_coords = [coord[0] for coord in zone.coordinates]
        y_coords = [coord[1] for coord in zone.coordinates]
        
        center_x = sum(x_coords) / len(x_coords)
        center_y = sum(y_coords) / len(y_coords)
        
        return (center_x, center_y)
    
    def _calculate_route(
        self,
        start_zone: Zone,
        start_point: Tuple[float, float],
        exit_point: ExitPoint,
        obstacles: List[Tuple[float, float, float, float]] = None,
        emergency_level: EmergencyLevel = EmergencyLevel.WARNING
    ) -> Optional[EvacuationRoute]:
        """计算单条路径"""
        try:
            # 使用A*算法计算路径
            waypoints = self._astar_pathfinding(
                start_point, exit_point.coordinates, obstacles
            )
            
            if not waypoints:
                return None
            
            # 计算路径距离
            distance = self._calculate_path_distance(waypoints)
            
            # 估算疏散时间（基于人员移动速度）
            walking_speed = 1.2  # 米/秒
            if emergency_level in [EmergencyLevel.EMERGENCY, EmergencyLevel.CRITICAL]:
                walking_speed = 2.0  # 紧急情况下移动更快
            
            estimated_time = distance / walking_speed / 60  # 转换为分钟
            
            # 估算路径容量
            path_width = 2.0  # 假设路径宽度2米
            capacity = int(path_width * 60)  # 每分钟通过人数
            
            # 设置优先级
            priority = self._calculate_route_priority(
                distance, exit_point, emergency_level
            )
            
            route = EvacuationRoute(
                route_id=str(uuid4()),
                route_name=f"从{start_zone.zone_name}到{exit_point.exit_name}",
                start_zone=start_zone.zone_id,
                end_exit=exit_point.exit_id,
                waypoints=waypoints,
                distance=distance,
                estimated_time=estimated_time,
                capacity=capacity,
                priority=priority,
                accessibility_level=2 if exit_point.accessibility_features else 1
            )
            
            return route
            
        except Exception as e:
            logger.error(f"Failed to calculate route: {e}")
            return None
    
    def _astar_pathfinding(
        self,
        start: Tuple[float, float],
        goal: Tuple[float, float],
        obstacles: List[Tuple[float, float, float, float]] = None
    ) -> List[Tuple[float, float]]:
        """A*路径规划算法"""
        # 简化的A*实现
        # 在实际应用中，应该使用更复杂的网格或图结构
        
        def heuristic(a: Tuple[float, float], b: Tuple[float, float]) -> float:
            return np.sqrt((a[0] - b[0])**2 + (a[1] - b[1])**2)
        
        def is_obstacle(point: Tuple[float, float]) -> bool:
            if not obstacles:
                return False
            
            x, y = point
            for ox, oy, ow, oh in obstacles:
                if ox <= x <= ox + ow and oy <= y <= oy + oh:
                    return True
            return False
        
        # 简化路径：直接连接起点和终点，避开障碍物
        waypoints = [start]
        
        # 检查直线路径是否有障碍物
        if not self._line_intersects_obstacles(start, goal, obstacles):
            waypoints.append(goal)
        else:
            # 简单的绕行策略
            mid_x = (start[0] + goal[0]) / 2
            mid_y = (start[1] + goal[1]) / 2
            
            # 尝试几个中间点
            for offset in [(50, 0), (-50, 0), (0, 50), (0, -50)]:
                mid_point = (mid_x + offset[0], mid_y + offset[1])
                if (not is_obstacle(mid_point) and 
                    not self._line_intersects_obstacles(start, mid_point, obstacles) and
                    not self._line_intersects_obstacles(mid_point, goal, obstacles)):
                    waypoints.append(mid_point)
                    break
            
            waypoints.append(goal)
        
        return waypoints
    
    def _line_intersects_obstacles(
        self,
        start: Tuple[float, float],
        end: Tuple[float, float],
        obstacles: List[Tuple[float, float, float, float]] = None
    ) -> bool:
        """检查线段是否与障碍物相交"""
        if not obstacles:
            return False
        
        # 简化的相交检测
        for ox, oy, ow, oh in obstacles:
            # 检查线段是否与矩形相交
            if self._line_rect_intersect(start, end, (ox, oy, ox + ow, oy + oh)):
                return True
        
        return False
    
    def _line_rect_intersect(
        self,
        line_start: Tuple[float, float],
        line_end: Tuple[float, float],
        rect: Tuple[float, float, float, float]
    ) -> bool:
        """检查线段与矩形是否相交"""
        # 简化的相交检测
        x1, y1 = line_start
        x2, y2 = line_end
        rx1, ry1, rx2, ry2 = rect
        
        # 检查线段端点是否在矩形内
        if (rx1 <= x1 <= rx2 and ry1 <= y1 <= ry2) or (rx1 <= x2 <= rx2 and ry1 <= y2 <= ry2):
            return True
        
        # 简化的线段-矩形相交检测
        return False
    
    def _calculate_path_distance(self, waypoints: List[Tuple[float, float]]) -> float:
        """计算路径总距离"""
        total_distance = 0.0
        
        for i in range(len(waypoints) - 1):
            x1, y1 = waypoints[i]
            x2, y2 = waypoints[i + 1]
            distance = np.sqrt((x2 - x1)**2 + (y2 - y1)**2)
            total_distance += distance
        
        return total_distance
    
    def _calculate_route_priority(
        self,
        distance: float,
        exit_point: ExitPoint,
        emergency_level: EmergencyLevel
    ) -> int:
        """计算路径优先级"""
        priority = 3  # 默认优先级
        
        # 距离因子
        if distance < 100:
            priority += 1
        elif distance > 300:
            priority -= 1
        
        # 出口类型因子
        if exit_point.is_emergency_exit:
            priority += 1
        
        # 紧急程度因子
        if emergency_level == EmergencyLevel.CRITICAL:
            priority += 1
        elif emergency_level == EmergencyLevel.NORMAL:
            priority -= 1
        
        return max(1, min(5, priority))


class EvacuationService:
    """疏散服务"""
    
    def __init__(self):
        self.zones: Dict[str, Zone] = {}
        self.exit_points: Dict[str, ExitPoint] = {}
        self.evacuation_routes: Dict[str, EvacuationRoute] = {}
        self.evacuation_plans: Dict[str, EvacuationPlan] = {}
        self.active_evacuations: Dict[str, EvacuationEvent] = {}
        self.evacuation_history: List[EvacuationEvent] = []
        
        self.pathfinding = PathfindingAlgorithm()
        
        # 服务状态
        self._running = False
        self._monitoring_task = None
        self.monitoring_interval = 10.0  # 10秒检查一次
        
        # 统计信息
        self.stats = {
            'total_evacuations': 0,
            'successful_evacuations': 0,
            'cancelled_evacuations': 0,
            'average_duration': 0.0
        }
        
        # 初始化默认配置
        self._initialize_default_config()
    
    def _initialize_default_config(self):
        """初始化默认配置"""
        # 默认出口点
        main_exit = ExitPoint(
            exit_id="main_exit",
            exit_name="主出口",
            coordinates=(400, 0),
            capacity=120,  # 每分钟120人
            is_emergency_exit=False,
            accessibility_features=["wheelchair_accessible", "wide_door"]
        )
        self.exit_points[main_exit.exit_id] = main_exit
        
        emergency_exit = ExitPoint(
            exit_id="emergency_exit",
            exit_name="紧急出口",
            coordinates=(800, 300),
            capacity=60,
            is_emergency_exit=True,
            accessibility_features=["emergency_lighting"]
        )
        self.exit_points[emergency_exit.exit_id] = emergency_exit
        
        # 默认疏散计划
        crowd_evacuation_plan = EvacuationPlan(
            plan_id="crowd_evacuation",
            plan_name="人群聚集疏散计划",
            trigger_conditions={
                'density_level': {'operator': '>=', 'value': 'high'},
                'person_count': {'operator': '>', 'value': 15}
            },
            affected_zones=["central", "entrance"],
            evacuation_routes=[],  # 将在运行时计算
            estimated_duration=10.0,
            max_occupancy=100,
            emergency_level=EmergencyLevel.WARNING
        )
        self.evacuation_plans[crowd_evacuation_plan.plan_id] = crowd_evacuation_plan
        
        emergency_evacuation_plan = EvacuationPlan(
            plan_id="emergency_evacuation",
            plan_name="紧急疏散计划",
            trigger_conditions={
                'emergency_level': 'critical',
                'anomaly_type': 'overcrowding'
            },
            affected_zones=["central", "entrance", "exit"],
            evacuation_routes=[],
            estimated_duration=5.0,
            max_occupancy=200,
            priority_groups=["elderly", "disabled", "children"],
            emergency_level=EmergencyLevel.CRITICAL
        )
        self.evacuation_plans[emergency_evacuation_plan.plan_id] = emergency_evacuation_plan
    
    async def start_monitoring(self):
        """启动监控服务"""
        if self._running:
            return
        
        self._running = True
        self._monitoring_task = asyncio.create_task(self._monitoring_loop())
        logger.info("Evacuation monitoring service started")
    
    async def stop_monitoring(self):
        """停止监控服务"""
        self._running = False
        if self._monitoring_task:
            self._monitoring_task.cancel()
            try:
                await self._monitoring_task
            except asyncio.CancelledError:
                pass
        logger.info("Evacuation monitoring service stopped")
    
    async def _monitoring_loop(self):
        """监控循环"""
        while self._running:
            try:
                await self._check_evacuation_triggers()
                await self._update_evacuation_progress()
                await asyncio.sleep(self.monitoring_interval)
            except asyncio.CancelledError:
                break
            except Exception as e:
                logger.error(f"Error in monitoring loop: {e}")
                await asyncio.sleep(5.0)
    
    async def _check_evacuation_triggers(self):
        """检查疏散触发条件"""
        # 这里应该从密度分析服务获取当前状态
        # 为了演示，使用模拟数据
        current_conditions = {
            'density_level': 'medium',
            'person_count': 12,
            'emergency_level': 'normal'
        }
        
        for plan in self.evacuation_plans.values():
            if plan.is_triggered(current_conditions):
                # 检查是否已经有活跃的疏散
                existing_evacuation = any(
                    event.plan_id == plan.plan_id and event.status in [
                        EvacuationStatus.INITIATED, EvacuationStatus.IN_PROGRESS
                    ]
                    for event in self.active_evacuations.values()
                )
                
                if not existing_evacuation:
                    await self._initiate_evacuation(plan, current_conditions)
    
    async def _update_evacuation_progress(self):
        """更新疏散进度"""
        for event in list(self.active_evacuations.values()):
            if event.status == EvacuationStatus.IN_PROGRESS:
                # 模拟进度更新
                elapsed_time = (datetime.now() - event.trigger_time).total_seconds() / 60
                estimated_duration = self.evacuation_plans[event.plan_id].estimated_duration
                
                progress = min(1.0, elapsed_time / estimated_duration)
                event.progress = progress
                
                # 检查是否完成
                if progress >= 1.0:
                    await self._complete_evacuation(event.event_id)
    
    async def process_density_measurement(self, measurement: DensityMeasurement):
        """处理密度测量结果"""
        current_conditions = {
            'camera_id': measurement.camera_id,
            'density_level': measurement.density_level.value,
            'person_count': measurement.person_count,
            'density_value': measurement.density_value,
            'timestamp': measurement.timestamp
        }
        
        # 检查是否触发疏散计划
        for plan in self.evacuation_plans.values():
            if plan.is_triggered(current_conditions):
                existing_evacuation = any(
                    event.plan_id == plan.plan_id and 
                    event.camera_id == measurement.camera_id and
                    event.status in [EvacuationStatus.INITIATED, EvacuationStatus.IN_PROGRESS]
                    for event in self.active_evacuations.values()
                )
                
                if not existing_evacuation:
                    await self._initiate_evacuation(plan, current_conditions)
    
    async def process_density_anomaly(self, anomaly: DensityAnomaly):
        """处理密度异常"""
        if anomaly.anomaly_type == "overcrowding" and anomaly.severity in [AlertLevel.HIGH, AlertLevel.CRITICAL]:
            current_conditions = {
                'camera_id': anomaly.camera_id,
                'anomaly_type': anomaly.anomaly_type,
                'severity': anomaly.severity.value,
                'emergency_level': 'critical' if anomaly.severity == AlertLevel.CRITICAL else 'warning',
                'current_density': anomaly.current_density
            }
            
            # 触发紧急疏散计划
            emergency_plan = self.evacuation_plans.get("emergency_evacuation")
            if emergency_plan and emergency_plan.is_triggered(current_conditions):
                await self._initiate_evacuation(emergency_plan, current_conditions)
    
    async def _initiate_evacuation(self, plan: EvacuationPlan, conditions: Dict[str, Any]):
        """启动疏散"""
        try:
            # 计算疏散路径
            evacuation_routes = await self._calculate_evacuation_routes(plan, conditions)
            
            # 创建疏散事件
            event = EvacuationEvent(
                event_id=str(uuid4()),
                plan_id=plan.plan_id,
                camera_id=conditions.get('camera_id', 'unknown'),
                trigger_time=datetime.now(),
                status=EvacuationStatus.INITIATED,
                emergency_level=plan.emergency_level,
                affected_zones=plan.affected_zones,
                estimated_people=conditions.get('person_count', 0),
                evacuation_routes=[route.route_id for route in evacuation_routes],
                metadata=conditions
            )
            
            self.active_evacuations[event.event_id] = event
            self.stats['total_evacuations'] += 1
            
            # 更新路径占用情况
            for route in evacuation_routes:
                route.current_occupancy += event.estimated_people // len(evacuation_routes)
                self.evacuation_routes[route.route_id] = route
            
            # 发送疏散指令
            await self._send_evacuation_instructions(event, evacuation_routes)
            
            # 更新状态为进行中
            event.status = EvacuationStatus.IN_PROGRESS
            
            logger.info(f"Evacuation initiated: {event.event_id} for plan {plan.plan_id}")
            
        except Exception as e:
            logger.error(f"Failed to initiate evacuation: {e}")
    
    async def _calculate_evacuation_routes(
        self, 
        plan: EvacuationPlan, 
        conditions: Dict[str, Any]
    ) -> List[EvacuationRoute]:
        """计算疏散路径"""
        # 获取受影响的区域
        affected_zones = [
            zone for zone_id, zone in self.zones.items() 
            if zone_id in plan.affected_zones
        ]
        
        # 获取可用出口
        available_exits = [
            exit_point for exit_point in self.exit_points.values()
            if exit_point.status != RouteStatus.BLOCKED
        ]
        
        # 使用路径规划算法计算最优路径
        routes = self.pathfinding.find_optimal_routes(
            affected_zones, available_exits, emergency_level=plan.emergency_level
        )
        
        # 选择最佳路径（限制数量）
        max_routes = 3 if plan.emergency_level == EmergencyLevel.CRITICAL else 2
        selected_routes = routes[:max_routes]
        
        return selected_routes
    
    async def _send_evacuation_instructions(
        self, 
        event: EvacuationEvent, 
        routes: List[EvacuationRoute]
    ):
        """发送疏散指令"""
        # 构建疏散指令
        instructions = {
            'event_id': event.event_id,
            'emergency_level': event.emergency_level.value,
            'message': self._generate_evacuation_message(event),
            'routes': [
                {
                    'route_id': route.route_id,
                    'route_name': route.route_name,
                    'waypoints': route.waypoints,
                    'estimated_time': route.estimated_time,
                    'priority': route.priority
                }
                for route in routes
            ],
            'timestamp': event.trigger_time.isoformat()
        }
        
        # 这里应该发送到各种通知渠道
        # 例如：广播系统、移动应用、显示屏等
        logger.info(f"Evacuation instructions sent: {instructions}")
        
        # 模拟发送到不同渠道
        await self._broadcast_to_speakers(instructions)
        await self._send_to_mobile_apps(instructions)
        await self._update_digital_signs(instructions)
    
    def _generate_evacuation_message(self, event: EvacuationEvent) -> str:
        """生成疏散消息"""
        if event.emergency_level == EmergencyLevel.CRITICAL:
            return "紧急疏散！请立即按照指示路径有序撤离，保持冷静！"
        elif event.emergency_level == EmergencyLevel.EMERGENCY:
            return "请注意！检测到异常情况，请按照指示路径撤离。"
        elif event.emergency_level == EmergencyLevel.WARNING:
            return "人员密度较高，建议按照指示路径分流。"
        else:
            return "请注意人员分流指引。"
    
    async def _broadcast_to_speakers(self, instructions: Dict[str, Any]):
        """广播到扬声器"""
        message = instructions['message']
        logger.info(f"Broadcasting to speakers: {message}")
        # 实际实现中应该调用音响系统API
    
    async def _send_to_mobile_apps(self, instructions: Dict[str, Any]):
        """发送到移动应用"""
        logger.info("Sending evacuation instructions to mobile apps")
        # 实际实现中应该调用推送服务API
    
    async def _update_digital_signs(self, instructions: Dict[str, Any]):
        """更新数字标牌"""
        logger.info("Updating digital signs with evacuation routes")
        # 实际实现中应该调用数字标牌系统API
    
    async def _complete_evacuation(self, event_id: str):
        """完成疏散"""
        if event_id not in self.active_evacuations:
            return
        
        event = self.active_evacuations[event_id]
        event.status = EvacuationStatus.COMPLETED
        event.completion_time = datetime.now()
        event.progress = 1.0
        
        # 释放路径占用
        for route_id in event.evacuation_routes:
            if route_id in self.evacuation_routes:
                route = self.evacuation_routes[route_id]
                route.current_occupancy = max(0, route.current_occupancy - event.estimated_people // len(event.evacuation_routes))
        
        # 移动到历史记录
        self.evacuation_history.append(event)
        del self.active_evacuations[event_id]
        
        # 更新统计
        self.stats['successful_evacuations'] += 1
        duration = (event.completion_time - event.trigger_time).total_seconds() / 60
        self.stats['average_duration'] = (
            (self.stats['average_duration'] * (self.stats['successful_evacuations'] - 1) + duration) /
            self.stats['successful_evacuations']
        )
        
        logger.info(f"Evacuation completed: {event_id}")
    
    async def cancel_evacuation(self, event_id: str, reason: str = "Manual cancellation") -> bool:
        """取消疏散"""
        if event_id not in self.active_evacuations:
            return False
        
        event = self.active_evacuations[event_id]
        event.status = EvacuationStatus.CANCELLED
        event.cancelled_time = datetime.now()
        event.cancellation_reason = reason
        
        # 释放路径占用
        for route_id in event.evacuation_routes:
            if route_id in self.evacuation_routes:
                route = self.evacuation_routes[route_id]
                route.current_occupancy = max(0, route.current_occupancy - event.estimated_people // len(event.evacuation_routes))
        
        # 移动到历史记录
        self.evacuation_history.append(event)
        del self.active_evacuations[event_id]
        
        # 更新统计
        self.stats['cancelled_evacuations'] += 1
        
        logger.info(f"Evacuation cancelled: {event_id}, reason: {reason}")
        return True
    
    def add_zone(self, zone: Zone):
        """添加区域"""
        self.zones[zone.zone_id] = zone
        logger.info(f"Added evacuation zone: {zone.zone_id}")
    
    def add_exit_point(self, exit_point: ExitPoint):
        """添加出口点"""
        self.exit_points[exit_point.exit_id] = exit_point
        logger.info(f"Added exit point: {exit_point.exit_id}")
    
    def add_evacuation_plan(self, plan: EvacuationPlan):
        """添加疏散计划"""
        self.evacuation_plans[plan.plan_id] = plan
        logger.info(f"Added evacuation plan: {plan.plan_id}")
    
    def update_exit_status(self, exit_id: str, status: RouteStatus, current_load: int = None):
        """更新出口状态"""
        if exit_id in self.exit_points:
            exit_point = self.exit_points[exit_id]
            exit_point.status = status
            if current_load is not None:
                exit_point.current_load = current_load
            logger.info(f"Updated exit {exit_id} status to {status}")
    
    def get_active_evacuations(self) -> List[EvacuationEvent]:
        """获取活跃疏散事件"""
        return list(self.active_evacuations.values())
    
    def get_evacuation_history(
        self, 
        limit: int = 100,
        start_time: Optional[datetime] = None,
        end_time: Optional[datetime] = None
    ) -> List[EvacuationEvent]:
        """获取疏散历史"""
        history = self.evacuation_history
        
        if start_time:
            history = [e for e in history if e.trigger_time >= start_time]
        
        if end_time:
            history = [e for e in history if e.trigger_time <= end_time]
        
        # 按时间倒序排列
        history.sort(key=lambda x: x.trigger_time, reverse=True)
        
        return history[:limit]
    
    def get_evacuation_statistics(self) -> Dict[str, Any]:
        """获取疏散统计"""
        return {
            'total_evacuations': self.stats['total_evacuations'],
            'successful_evacuations': self.stats['successful_evacuations'],
            'cancelled_evacuations': self.stats['cancelled_evacuations'],
            'success_rate': (
                self.stats['successful_evacuations'] / self.stats['total_evacuations']
                if self.stats['total_evacuations'] > 0 else 0
            ),
            'average_duration': self.stats['average_duration'],
            'active_evacuations': len(self.active_evacuations),
            'available_exits': len([
                e for e in self.exit_points.values() 
                if e.status == RouteStatus.AVAILABLE
            ]),
            'evacuation_plans': len(self.evacuation_plans)
        }
    
    def get_evacuation_routes(self) -> List[EvacuationRoute]:
        """获取疏散路径"""
        return list(self.evacuation_routes.values())
    
    def get_exit_points(self) -> List[ExitPoint]:
        """获取出口点"""
        return list(self.exit_points.values())
    
    def get_evacuation_plans(self) -> List[EvacuationPlan]:
        """获取疏散计划"""
        return list(self.evacuation_plans.values())


# 全局疏散服务实例
evacuation_service = EvacuationService()